﻿// <copyright file="DirectionalLight.cs" company="Axelerate Solutions S.A.">
// Copyright (c) Axelerate Solutions S.A.  All rights reserved.
// </copyright>

namespace Axelerate.Silverlight3D.Media.Media3D
{
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    /// <summary>
    /// File name: DirectionalLight.cs
    /// Company: Axelerate Solutions S.A.
    /// Created By: Daniel Rojas
    /// Created Date: 10/17/2008 15:32:00 h.
    /// Description: Light object that projects its effect along a direction specified by a Vector3D.
    ///   <Modifications>
    ///   </Modifications>
    /// </summary>
    public sealed class DirectionalLight : Light
    {
        #region Fields
        /// <summary>
        /// Identifies the LookDirection dependency property..
        /// </summary>
        public static readonly DependencyProperty DirectionProperty =
                    DependencyProperty.Register(
                          "Direction",
                          typeof(Vector3D),
                          typeof(DirectionalLight),
                          new PropertyMetadata(OnDirectionPropertyChanged));
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets a value that represents the vector along which the light's effect will be seen on models in a 3-D scene. This is a dependency property.
        /// </summary>
        public Vector3D Direction
        {
            get
            {
                return (Vector3D)this.GetValue(DirectionProperty);
            }
            set
            {
                this.SetValue(DirectionProperty, value);
            }
        }
        #endregion

        #region Methods

        /// <summary>
        /// Raise the Direction changed event
        /// </summary>
        /// <param name="d">DependencyObject owner of the property</param>
        /// <param name="e">DependencyPropertyChangedEventArgs with the necesary information</param>
        private static void OnDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DirectionalLight)d).NotifyPropertyChanged("Direction");
            ((DirectionalLight)d).IsDirty = true;
        }

        #endregion

        #region Constructors
        
        /// <summary>
        /// Creates an instance of a light that projects its effect in a specified direction.
        /// </summary>
        public DirectionalLight() : base()
        {
        }

        /// <summary>
        /// Creates an instance of a light that projects its effect along a specified Vector3D with a specified color.
        /// </summary>
        /// <param name="diffuseColor">Diffuse color of the new light.</param>
        /// <param name="direction">Direction of the new light.</param>
        public DirectionalLight(Color diffuseColor, Vector3D direction)
        {
            this.Color = diffuseColor;
            this.Direction = direction;
        }
        #endregion

        /// <summary>
        /// Get the bounds of the object. in this case is a Empty rect3D
        /// </summary>
        /// <returns></returns>
        protected override Rect3D GetBounds()
        {
            return Rect3D.Empty;    
        }

        /// <summary>
        /// Caculated the color intencity. I use a point3D because i need return a double for r,g,b components and was more easy see the intencity of the color as a x,y,z point.
        /// </summary>
        /// <param name="Normal">Normal direction of the surface that is impacting the light</param>
        /// <returns>return a Point3D with the intencity of the r,g,b components on the x,y,z properties</returns>
        internal override Point3D GetColorIntencityByNormal(Vector3D Normal)
        {
            Vector3D dirNormalized = this.Direction;
            dirNormalized.Normalize();

            Normal.Normalize();
            double cosAngle = Vector3D.DotProduct(dirNormalized, Normal);
            if (cosAngle < 0)
            {
                cosAngle = 0;
            }

            return new Point3D(((double)this.Color.B / 255) * cosAngle, ((double)this.Color.G / 255) * cosAngle, ((double)this.Color.B / 255) * cosAngle);
        }

    }
}
